
import com.sun.xml.internal.ws.util.ByteArrayBuffer;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.JPanel;
import javax.xml.transform.TransformerException;
import messages.GetLedStateMessage;
import messages.GetTempMessage;
import messages.LedStateMessage;
import messages.Message;
import messages.TempMessage;
import messages.ToggleBlueMessage;
import messages.ToggleRedMessage;

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */


/**
 *
 * @author Tyulen
 */
public class MainFrame extends javax.swing.JFrame {

    /**
     * Creates new form MainFrame
     */
    Socket sock;
    InputStream input;
    OutputStream output;
    boolean connected = false;
    Image onState;
    Image offState;
    Thread running;
    Thread sendTempRequest;
    long startMills;
    
    public MainFrame() throws IOException {
        initComponents();
        initUserComponents();
    }
    private void execute(Properties data) {
        switch(Byte.parseByte(data.getProperty("id"))) {
            case Message.ledState:
                LedStateMessage m = new LedStateMessage(data);
                if (m.red) {
                    ((ImagePanel)redView).setImage(onState, Color.red);
                } else {
                    ((ImagePanel)redView).setImage(offState, Color.red);
                }
                if (m.blue) {
                    ((ImagePanel)blueView).setImage(onState, Color.blue);
                } else {
                    ((ImagePanel)blueView).setImage(offState, Color.blue);
                }
                break;
            case Message.temp:
                long mills = System.currentTimeMillis();
                TempMessage m1 = new TempMessage(data);
                PlotPoint pp = new PlotPoint((mills - startMills) / 1000.0, m1.value);
                plotter.addPoint(pp);
                while (pp.getX() >= plotter.getLastX()) {
                    plotter.addMoveForward();
                }
                break;
        }
    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        connect = new javax.swing.JButton();
        address = new javax.swing.JTextField();
        jTabbedPane2 = new javax.swing.JTabbedPane();
        jPanel1 = new javax.swing.JPanel();
        rad = new javax.swing.JButton();
        state = new javax.swing.JButton();
        redView = new ImagePanel();
        blueView = new ImagePanel();
        blue = new javax.swing.JButton();
        plotter = new TempPlotter();
        getTemp = new javax.swing.JButton();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        connect.setText("connect");
        connect.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                connectActionPerformed(evt);
            }
        });

        rad.setText("red");
        rad.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                radActionPerformed(evt);
            }
        });

        state.setText("state");
        state.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                stateActionPerformed(evt);
            }
        });

        redView.setBackground(new java.awt.Color(102, 255, 102));

        javax.swing.GroupLayout redViewLayout = new javax.swing.GroupLayout(redView);
        redView.setLayout(redViewLayout);
        redViewLayout.setHorizontalGroup(
            redViewLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 0, Short.MAX_VALUE)
        );
        redViewLayout.setVerticalGroup(
            redViewLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 0, Short.MAX_VALUE)
        );

        blueView.setBackground(new java.awt.Color(153, 153, 255));

        javax.swing.GroupLayout blueViewLayout = new javax.swing.GroupLayout(blueView);
        blueView.setLayout(blueViewLayout);
        blueViewLayout.setHorizontalGroup(
            blueViewLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 0, Short.MAX_VALUE)
        );
        blueViewLayout.setVerticalGroup(
            blueViewLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 287, Short.MAX_VALUE)
        );

        blue.setText("blue");
        blue.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                blueActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
        jPanel1.setLayout(jPanel1Layout);
        jPanel1Layout.setHorizontalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel1Layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(rad, javax.swing.GroupLayout.DEFAULT_SIZE, 265, Short.MAX_VALUE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(state)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(blue, javax.swing.GroupLayout.DEFAULT_SIZE, 258, Short.MAX_VALUE)
                .addContainerGap())
            .addGroup(jPanel1Layout.createSequentialGroup()
                .addComponent(redView, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(blueView, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );
        jPanel1Layout.setVerticalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel1Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(rad)
                    .addComponent(state)
                    .addComponent(blue))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(blueView, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(redView, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
        );

        jTabbedPane2.addTab("Leds", jPanel1);

        javax.swing.GroupLayout plotterLayout = new javax.swing.GroupLayout(plotter);
        plotter.setLayout(plotterLayout);
        plotterLayout.setHorizontalGroup(
            plotterLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 616, Short.MAX_VALUE)
        );
        plotterLayout.setVerticalGroup(
            plotterLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 332, Short.MAX_VALUE)
        );

        jTabbedPane2.addTab("TempPlot", plotter);

        getTemp.setText("getTemp");
        getTemp.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                getTempActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jTabbedPane2, javax.swing.GroupLayout.Alignment.TRAILING)
                    .addComponent(connect, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(address)
                    .addComponent(getTemp, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addComponent(getTemp)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jTabbedPane2)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(connect)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(address, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap())
        );

        jTabbedPane2.getAccessibleContext().setAccessibleName("Leds");

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void connectActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_connectActionPerformed
        if (connected) {
	    return;
	}
	try {
            sock = new Socket(address.getText(), 2000);
            output = sock.getOutputStream();
            input = sock.getInputStream();
            address.setEditable(false);
            connected = true;
            running.start();
            //sendTempRequest.start();
	} catch (UnknownHostException ex) {
            Logger.getLogger(MainFrame.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(MainFrame.class.getName()).log(Level.SEVERE, null, ex);
        }
    }//GEN-LAST:event_connectActionPerformed

    private void radActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_radActionPerformed
        if (connected) {
            try {
                ToggleRedMessage m = new ToggleRedMessage();
                writeMessage(m);
            } catch (TransformerException ex) {
		Logger.getLogger(MainFrame.class.getName()).log(Level.SEVERE, null, ex);
	    } catch (IOException ex) {
                Logger.getLogger(MainFrame.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }//GEN-LAST:event_radActionPerformed

    private void blueActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_blueActionPerformed
        if (connected) {
            try {
                ToggleBlueMessage m = new ToggleBlueMessage();
                writeMessage(m);
            } catch (TransformerException ex) {
		Logger.getLogger(MainFrame.class.getName()).log(Level.SEVERE, null, ex);
	    } catch (IOException ex) {
                Logger.getLogger(MainFrame.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }//GEN-LAST:event_blueActionPerformed

    private void stateActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_stateActionPerformed
        if (connected) {
            try {
                GetLedStateMessage m = new GetLedStateMessage();
                writeMessage(m);
            } catch (TransformerException ex) {
		Logger.getLogger(MainFrame.class.getName()).log(Level.SEVERE, null, ex);
	    } catch (IOException ex) {
                Logger.getLogger(MainFrame.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }//GEN-LAST:event_stateActionPerformed

    private void getTempActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_getTempActionPerformed
        if (connected) {
            try {
                GetTempMessage m = new GetTempMessage();
                writeMessage(m);
            } catch (TransformerException ex) {
		Logger.getLogger(MainFrame.class.getName()).log(Level.SEVERE, null, ex);
	    } catch (IOException ex) {
                Logger.getLogger(MainFrame.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }//GEN-LAST:event_getTempActionPerformed

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        /* Set the Nimbus look and feel */
        //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
        /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
         * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html 
         */
        try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (ClassNotFoundException ex) {
            java.util.logging.Logger.getLogger(MainFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (InstantiationException ex) {
            java.util.logging.Logger.getLogger(MainFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            java.util.logging.Logger.getLogger(MainFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(MainFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        //</editor-fold>

        /* Create and display the form */
        java.awt.EventQueue.invokeLater(new Runnable() {
	    @Override
            public void run() {
                try {
                    new MainFrame().setVisible(true);
                } catch (IOException ex) {
                    Logger.getLogger(MainFrame.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        });
    }
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JTextField address;
    private javax.swing.JButton blue;
    private javax.swing.JPanel blueView;
    private javax.swing.JButton connect;
    private javax.swing.JButton getTemp;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JTabbedPane jTabbedPane2;
    private TempPlotter plotter;
    private javax.swing.JButton rad;
    private javax.swing.JPanel redView;
    private javax.swing.JButton state;
    // End of variables declaration//GEN-END:variables

    private void writeMessage(Message m) throws IOException, TransformerException {
	//m.getData().storeToXML(System.out, "");
	m.getData().storeToXML(output, "");
	output.write(255);
	output.flush();
    }

    private void initUserComponents() throws IOException {
        running = new Thread() {
            @Override
            public void run() {
                try {
                    ByteArrayBuffer buff = new ByteArrayBuffer();
                    while (true) {
                        if (connected) {
                            int readed = input.read();
                            if (readed != 255) {
                                buff.write(readed);
                            } else {
                                Properties message = new Properties();
                                message.loadFromXML(buff.newInputStream());
                                execute(message);
                                buff = new ByteArrayBuffer();
                            }
                        }
                    }
                } catch (IOException ex) {
                    Logger.getLogger(MainFrame.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        };
        
        sendTempRequest = new Thread() {
            private long lastMills = System.currentTimeMillis();
            private final long interval = 100;
            
            @Override
            public void run() {
                while (true) {
                    long mills = System.currentTimeMillis();
                    if (mills - lastMills >= interval) {
                        try {
                            GetTempMessage m = new GetTempMessage();
                            writeMessage(m);
                            lastMills = mills;
                        } catch (IOException ex) {
                            Logger.getLogger(MainFrame.class.getName()).log(Level.SEVERE, null, ex);
                        } catch (TransformerException ex) {
                            Logger.getLogger(MainFrame.class.getName()).log(Level.SEVERE, null, ex);
                        }
                    }
                }
            }
        };
        
        onState = ImageIO.read(new File("on.png"));
        offState = ImageIO.read(new File("off.png"));
        
        ((ImagePanel)redView).setImage(offState, Color.red);
        ((ImagePanel)blueView).setImage(offState, Color.blue);
        
        plotter.setYSize(50);
        plotter.setXSize(100);
        startMills = System.currentTimeMillis();
    }
}

class ImagePanel extends JPanel {
    Image image = null;
    Color fill = null;
    public void setImage(Image im, Color fill) {
        image = im;
        this.fill = fill;
        repaint();
    }
    
    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        if (image != null) {
            g.drawImage(image, 0, 0, getWidth(), getHeight(), fill, null);
        }
    }
}